{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {
    "slideshow": {
     "slide_type": "slide"
    }
   },
   "source": [
    "# Week 2\n",
    "\n",
    "**`Agent::API::base`**\n",
    "* `fit` method\n",
    "* private API (agent-specific)\n",
    "* public API (environment runner friendly)\n",
    "\n",
    "**`Environment::API::runner`**\n",
    "* fixed agent API\n",
    "* multiple episodes"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {
    "slideshow": {
     "slide_type": "skip"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "/Users/alpha/Developer/qtrader\n"
     ]
    }
   ],
   "source": [
    "# change current working directory\n",
    "%cd .."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {
    "slideshow": {
     "slide_type": "skip"
    }
   },
   "outputs": [],
   "source": [
    "# suppress warning messages\n",
    "import warnings\n",
    "warnings.filterwarnings('ignore')\n",
    "\n",
    "# trading environment\n",
    "from qtrader.envs import TradingEnv\n",
    "\n",
    "# YAML parser\n",
    "import yaml\n",
    "\n",
    "# OpenAI Gym\n",
    "import gym\n",
    "\n",
    "# # visualization\n",
    "import matplotlib.pyplot as plt"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {
    "slideshow": {
     "slide_type": "skip"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "start date: 2017-01-01\n",
      "trading frequency: W-FRI\n",
      "trading universe: ['AAPL', 'GE', 'JPM']\n",
      "number of episodes: 100\n"
     ]
    }
   ],
   "source": [
    "# fetch configuration file\n",
    "config = yaml.load(open('config/log/week_2.yaml', 'r'))\n",
    "\n",
    "# configuration summary\n",
    "print(f\"start date: {config['start_date']}\")\n",
    "print(f\"trading frequency: {config['freq']}\")\n",
    "print(f\"trading universe: {config['tickers']}\")\n",
    "print(f\"number of episodes: {config['num_episodes']}\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "slideshow": {
     "slide_type": "skip"
    }
   },
   "source": [
    "### Trading Environment\n",
    "\n",
    "Initialize a trading environment, with which the agents will interact."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {
    "slideshow": {
     "slide_type": "skip"
    }
   },
   "outputs": [],
   "source": [
    "# initialize environment\n",
    "env = TradingEnv(universe=config['tickers'],\n",
    "                 trading_period=config['freq'],\n",
    "                 csv=config['csv_file_prices'])"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "slideshow": {
     "slide_type": "slide"
    }
   },
   "source": [
    "## `Agent`\n",
    "\n",
    "Base class for agents that complies with interface for automatic execution of environment.\n",
    "* **private**: agent-specific methods\n",
    "* **public**: API accessed by the `run` method"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {
    "slideshow": {
     "slide_type": "skip"
    }
   },
   "outputs": [],
   "source": [
    "class Agent:\n",
    "    \"\"\"Base class for agents in OpenAI Gym\n",
    "    compatible environments.\"\"\"\n",
    "\n",
    "    _id = 'base'\n",
    "\n",
    "    def __init__(self, **kwargs):\n",
    "        raise NotImplementedError\n",
    "\n",
    "    #######\n",
    "    # API\n",
    "    #######\n",
    "\n",
    "    @property\n",
    "    def name(self):\n",
    "        return self._id\n",
    "\n",
    "    def begin_episode(self, observation):\n",
    "        pass\n",
    "\n",
    "    def act(self, observation):\n",
    "        raise NotImplementedError\n",
    "\n",
    "    def observe(self, observation, action, reward, done, next_observation):\n",
    "        pass\n",
    "\n",
    "    def end_episode(self):\n",
    "        pass\n",
    "    \n",
    "    def fit(self, env, num_episodes=1, verbose=False):\n",
    "        return run(env, self, num_episodes, True, verbose)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "slideshow": {
     "slide_type": "slide"
    }
   },
   "source": [
    "### `RandomAgent`\n",
    "\n",
    "Example random agent, implementing the common interface.\n",
    "Suitable to implement `act` method only."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {
    "slideshow": {
     "slide_type": "skip"
    }
   },
   "outputs": [],
   "source": [
    "class RandomAgent(Agent):\n",
    "    \"\"\"Random agent.\"\"\"\n",
    "\n",
    "    _id = 'random'\n",
    "\n",
    "    def __init__(self, action_space):\n",
    "        self.action_space = action_space\n",
    "\n",
    "    #######\n",
    "    # API\n",
    "    #######\n",
    "\n",
    "    def act(self, observation):\n",
    "        \"\"\"Randomly sample an action\n",
    "        from action space.\"\"\"\n",
    "        return self.action_space.sample()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "slideshow": {
     "slide_type": "slide"
    }
   },
   "source": [
    "## `run`\n",
    "\n",
    "OpenAI gym environments automated execution runner."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {
    "slideshow": {
     "slide_type": "skip"
    }
   },
   "outputs": [],
   "source": [
    "def run(env, agent, num_episodes, record, log):\n",
    "    \"\"\"Run episode on the `env` using `agent`.\n",
    "\n",
    "    Parameters\n",
    "    ----------\n",
    "    env: gym.Env\n",
    "        OpenAI Gym compatible environment\n",
    "    agent: qtrader.agent.base.Agent\n",
    "        Agent to interact with the environment\n",
    "    num_episodes: int\n",
    "        Number of episodes to run\n",
    "    record: bool\n",
    "        Keep record of actions & rewards for each step\n",
    "    log: bool\n",
    "        Flag for logging at the end of each episode\n",
    "\n",
    "    Returns\n",
    "    -------\n",
    "    rewards: list\n",
    "        List of rewards per step per episode\n",
    "    actions: list\n",
    "        List of actions per step per episode\n",
    "    \"\"\"\n",
    "    # unregister all agents from environment\n",
    "    if hasattr(env, 'unregister'):\n",
    "        # when agent=None, all agents unregistered\n",
    "        env.unregister(agent=None)\n",
    "    # register agent to environment if needed\n",
    "    if hasattr(env, 'register'):\n",
    "        # assign random name if not given\n",
    "        if not hasattr(agent, 'name'):\n",
    "            agent.name = '_default'\n",
    "        # register agent, duplicates are ignored\n",
    "        env.register(agent)\n",
    "    # initialize rewards buffer\n",
    "    rewards = []\n",
    "    # initialize actions buffer\n",
    "    actions = []\n",
    "\n",
    "    def _run():\n",
    "        \"\"\"Closure runner for each episode.\"\"\"\n",
    "        # initialize rewards local buffer\n",
    "        _rewards = []\n",
    "        # initialize actions local buffer\n",
    "        _actions = []\n",
    "        # environment: reset & fetch observation\n",
    "        ob = env.reset()\n",
    "        # initialize reward\n",
    "        reward = 0.0\n",
    "        # termination flag\n",
    "        done = False\n",
    "        # environment state information\n",
    "        info = {}\n",
    "        # iterator for maximum episode steps\n",
    "        j = 0\n",
    "        # agent closure: beginning of episode\n",
    "        agent.begin_episode(ob)\n",
    "        # interaction loop\n",
    "        while (not done) and (j < env._max_episode_steps):\n",
    "            # agent closure: determine action\n",
    "            action = agent.act(ob)\n",
    "            # class 1: trading environments\n",
    "            if hasattr(env, 'register'):\n",
    "                # environment: take action\n",
    "                ob_, reward, done, info = env.step({agent.name: action})\n",
    "                # fetch agent-specific reward\n",
    "                reward = reward[agent.name]\n",
    "            # class 2: vanilla environments\n",
    "            else:\n",
    "                # environment: take action\n",
    "                ob_, reward, done, info = env.step(action)\n",
    "            # store reward\n",
    "            _rewards.append(reward)\n",
    "            # store action\n",
    "            _actions.append(action)\n",
    "            # agent closure: observe\n",
    "            agent.observe(ob, action, reward, done, ob_)\n",
    "            # set new observation to current\n",
    "            ob = ob_\n",
    "            # increment iterator\n",
    "            j = j + 1\n",
    "        # agent closure: end of episode\n",
    "        agent.end_episode()\n",
    "        return _rewards, _actions\n",
    "\n",
    "    for e in range(num_episodes):\n",
    "        # run episode\n",
    "        R, A = _run()\n",
    "        # episode-wise records\n",
    "        if record:\n",
    "            # store rewards\n",
    "            rewards.append(R)\n",
    "            # store actions\n",
    "            actions.append(A)\n",
    "        # log cumulative rewards\n",
    "        if log:\n",
    "            print('episode: %4d, cumulative reward: %+.5f' % (e, sum(R)))\n",
    "    return rewards, actions"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "slideshow": {
     "slide_type": "slide"
    }
   },
   "source": [
    "### Experiments\n",
    "\n",
    "Combine `RandomAgent` and `run` on a common OpenAI environment, the **`CartPole-v1`**,\n",
    "and on the custom trading environment, the **`TradingEnv`**."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "slideshow": {
     "slide_type": "subslide"
    }
   },
   "source": [
    "#### `CartPole-v1`"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {
    "slideshow": {
     "slide_type": "skip"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\u001b[33mWARN: gym.spaces.Box autodetected dtype as <class 'numpy.float32'>. Please provide explicit dtype.\u001b[0m\n"
     ]
    }
   ],
   "source": [
    "# initialize environment\n",
    "env = gym.make('CartPole-v1')\n",
    "# initialize agent\n",
    "agent = RandomAgent(env.action_space)\n",
    "# execute environment\n",
    "rewards, actions = run(env, agent, config['num_episodes'], True, False)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {
    "slideshow": {
     "slide_type": "subslide"
    }
   },
   "outputs": [
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 1382.4x345.6 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "# initialize figure & axes\n",
    "fig, axes = plt.subplots(figsize=(19.2, 4.8))\n",
    "# plot cumulative reward per-episode\n",
    "for j in range(len(rewards)):\n",
    "    axes.bar(j+1, sum(rewards[j]), color='g')\n",
    "# axes settings\n",
    "axes.set(title='CartPole-v1: Score per Episode', ylabel='Score', xlabel='Episode, #');"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "slideshow": {
     "slide_type": "subslide"
    }
   },
   "source": [
    "#### `TradingEnv`"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {
    "slideshow": {
     "slide_type": "skip"
    }
   },
   "outputs": [],
   "source": [
    "# initialize environment\n",
    "env = TradingEnv(universe=config['tickers'],\n",
    "                 trading_period=config['freq'],\n",
    "                 start_date=config['start_date'],\n",
    "                 csv=config['csv_file_prices'])\n",
    "# initialize agent\n",
    "agent = RandomAgent(action_space=env.action_space)\n",
    "# execute environment\n",
    "rewards, actions = run(env, agent, config['num_episodes'], True, False)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {
    "slideshow": {
     "slide_type": "subslide"
    }
   },
   "outputs": [
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 1382.4x345.6 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "# initialize figure & axes\n",
    "fig, axes = plt.subplots(figsize=(19.2, 4.8))\n",
    "# plot cumulative reward per-episode\n",
    "for j in range(len(rewards)):\n",
    "    axes.bar(j+1, sum(rewards[j]), color='r')\n",
    "# axes settings\n",
    "axes.set(title='TradingEnv: Score per Episode', ylabel='Score', xlabel='Episode, #');"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "slideshow": {
     "slide_type": "slide"
    }
   },
   "source": [
    "## `agent.fit`\n",
    "\n",
    "Following `scikit-learn` API, the agent base class has a method **`fit`** which calls `run`\n",
    "internally for training the agent. The method can be reimplemented by derived agents."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {
    "slideshow": {
     "slide_type": "skip"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\u001b[33mWARN: gym.spaces.Box autodetected dtype as <class 'numpy.float32'>. Please provide explicit dtype.\u001b[0m\n"
     ]
    }
   ],
   "source": [
    "# initialize environment\n",
    "env = gym.make('CartPole-v1')\n",
    "# initialize agent\n",
    "agent = RandomAgent(env.action_space)\n",
    "# execute environment\n",
    "rewards, actions = agent.fit(env, config['num_episodes'])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {
    "slideshow": {
     "slide_type": "subslide"
    }
   },
   "outputs": [
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 1382.4x345.6 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "# initialize figure & axes\n",
    "fig, axes = plt.subplots(figsize=(19.2, 4.8))\n",
    "# plot cumulative reward per-episode\n",
    "for j in range(len(rewards)):\n",
    "    axes.bar(j+1, sum(rewards[j]), color='y')\n",
    "# axes settings\n",
    "axes.set(title='CartPole-v1: Score per Episode', ylabel='Score', xlabel='Episode, #');"
   ]
  }
 ],
 "metadata": {
  "celltoolbar": "Slideshow",
  "kernelspec": {
   "display_name": "qtrader",
   "language": "python",
   "name": "qtrader"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.6.5"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
